// es6类 是不能当做函数应用的 即 Animal() 而非 new Animal的话会报错
/*class Animal{
  constructor(type){
    this.type = type;
  }

  static flag = 'animal';

  static fn(){
    return 'fn';
  }

  eat(){
    console.log('eat');
  }
}

class Tiger extends Animal{
  constructor(type){
    super(type);
    console.log(this);
  }
  static fn(){
    return super.fn();
  }
  eat(){
    super.eat();
    console.log('吃肉');
  }
}

let tiger = new Tiger('哺乳类');
console.log(Tiger.fn());*/


"use strict";

function _typeof(obj) {
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
    _typeof = function _typeof(obj) {
      return typeof obj;
    };
  } else {
    _typeof = function _typeof(obj) {
      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol": typeof obj;
    };
  }
  return _typeof(obj);
}

function _possibleConstructorReturn(self, call) {
  if (call && (_typeof(call) === "object" || typeof call === "function")) {
    return call;
  }
  return _assertThisInitialized(self);
}

function _assertThisInitialized(self) { //只要不是undefined就会原样返回，否则报错
  if (self === void 0) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  return self;
}

function _get(target, property, receiver) {
  if (typeof Reflect !== "undefined" && Reflect.get) {
    _get = Reflect.get;
  } else {
    _get = function _get(target, property, receiver) {
      var base = _superPropBase(target, property); // 取到父类
      if (!base) return; // 如果不存在 拥有自己的property的父类 就返回
      var desc = Object.getOwnPropertyDescriptor(base, property);
      if (desc.get) { //如果设置了getter
        return desc.get.call(receiver);
      }
      return desc.value; //否则直接返回该property对应的值
    };
  }
  return _get(target, property, receiver || target);
}

function _superPropBase(object, property) {
  while (!Object.prototype.hasOwnProperty.call(object, property)) {
    object = _getPrototypeOf(object);
    if (object === null) break;
  }
  return object;
}

function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf: function _getPrototypeOf(o) {
    return o.__proto__ || Object.getPrototypeOf(o);
  };
  return _getPrototypeOf(o);
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  // 继承公共属性
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });
  // 继承父类的静态方法和属性 s
  if (superClass) _setPrototypeOf(subClass, superClass);
}

function _setPrototypeOf(o, p) {
  _setPrototypeOf = Object.setPrototypeOf ||
    function _setPrototypeOf(o, p) {
      o.__proto__ = p;
      return o;
    };
  return _setPrototypeOf(o, p);
}

function _instanceof(left, right) {
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
    return !! right[Symbol.hasInstance](left);
  } else {
    return left instanceof right;
  }
}
// 检查当前的this 是不是Constructor的实例
function _classCallCheck(instance, Constructor) {
  if (!_instanceof(instance, Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _defineProperties(target, props){
  for (var i = 0; i < props.length; ++i) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false; //默认不可被for in
    descriptor.configurable = true;
    if("value" in descriptor) descriptor.writable = true;
    /*
      采用的是defineProperty里value + writable而非设置set和get的方式定义属性
    */
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  /*
    //protoProps
    [{
      key: "eat"
      , value: function eat() {
        console.log('eat');
      }
    }]
  */
  if(protoProps) _defineProperties(Constructor.prototype, protoProps);
  if(staticProps) _defineProperties(Constructor, staticProps);
  return Constructor;
}

// _defineProperty(Animal,"flag",'animal')
function _defineProperty(obj, key, value){
  if(key in obj){ //如果是本身身上就有的属性(私有属性)，就将它变成可读可写可编辑的
    Object.defineProperty(obj, key, {
      value: value
      , enumerable: true
      , configurable: true
      , writable: true
    });
  }else{
    obj[key] = value;
  }
  return obj;
}

var Animal =
  /*#__PURE__*/
  function() {
    function Animal(type) {
      _classCallCheck(this, Animal);

      this.type = type;
    }

    _createClass(Animal, [{ /*原形上的*/
      key: "eat",
      value: function eat() {
        console.log('eat');
      }
    }], [{ /*静态的*/
      key: "fn",
      value: function fn() {
        return 'fn';
      }
    }]);

    return Animal;
  } ();


// 静态属性
_defineProperty(Animal, "flag", 'animal');

var Tiger =
  /*#__PURE__*/
  function(_Animal) {
    _inherits(Tiger, _Animal);

    // call + Object.create
    function Tiger(type) {
      var _this;

      _classCallCheck(this, Tiger);

      // super.call(this)
      //  _getPrototypeOf(Tiger)，因为之前的_inherits，Tiger已经__proto__指向Animal，故这里就等于Animal
      // So_getPrototypeOf(Tiger).call(this, type) 等价于 Animal.call(this,type)
      _this = _possibleConstructorReturn(this, _getPrototypeOf(Tiger).call(this, type));

      // console.log(this);
      console.log(_assertThisInitialized(_this));
      return _this;
    }

    _createClass(Tiger, [{
      key: "eat",
      value: function eat() {
        _get(_getPrototypeOf(Tiger.prototype), "eat", this).call(this);

        console.log('吃肉');
      }
    }], [{
      key: "fn",
      value: function fn() {
        return _get(_getPrototypeOf(Tiger), "fn", this).call(this);
      }
    }]);

    return Tiger;
  } (Animal);

var tiger = new Tiger('哺乳类');
console.log(Tiger.fn());


//this
//变量提升
//执行上下文 作用域链
//call bind apply
